function mk(el) {
    return $(document.createElement(el));
}

function Details(container, selection, sorting, zoom) {
    this.container = container;
    this.selection = selection;
    this.sorting   = sorting;
    this.zoom      = zoom;

    this.mkElement();
    selection.addChangeListener(this);
    zoom.addChangeListener(this);
}

Details.prototype.mkElement = function() {
    var _this = this;

    var controls = mk('div').addClass('controls');

    var up = mk('button').addClass('up').text(Unicode.UP_TRIANGLE + ' parent');
    up.prop('title', 'Jump to parent node');
    controls.append(up);

    var down = mk('button').addClass('down').text(
            Unicode.DOWN_TRIANGLE + ' zoom');
    down.prop('title', 'Zoom to this node');
    controls.append(down);

    var combo = mk('select').addClass('sorting');
    for (var k in Sorting.methods) {
        combo.append(mk('option').attr('value', k)
                .text(Sorting.methods[k].name));
    }
    combo.change(function() {
        _this.sorting.setMethodByKey(combo.val());
    });
    controls.append(combo);

    var canonical = mk('h1').addClass('canonical');

    var table = mk('table');

    table.append(mk('tr')
            .append(mk('td').text('Module'))
            .append(mk('td').append(mk('code').addClass('module'))));

    table.append(mk('tr')
            .append(mk('td').text('Entries'))
            .append(mk('td').addClass('entries')));

    table.append(mk('tr')
            .append(mk('td').text('Time'))
            .append(mk('td').addClass('time')));

    table.append(mk('tr')
            .append(mk('td').text('Alloc'))
            .append(mk('td').addClass('alloc')));

    table.append(mk('tr')
            .append(mk('td').text('Src'))
            .append(mk('td').append(mk('code').addClass('src'))));

    table.append(mk('tr').addClass('mainTimeRow')
            .append(mk('td').text('MAIN Time'))
            .append(mk('td').addClass('mainTime')));

    table.append(mk('tr').addClass('mainAllocRow')
            .append(mk('td').text('MAIN Alloc'))
            .append(mk('td').addClass('mainAlloc')));

    var credits = mk('p').addClass('credits');
    credits.html('Generated by ' +
        '<a href="http://github.com/jaspervdj/profiteur" ' +
        'target="_blank">profiteur</a>.');

    this.container.append(controls);
    this.container.append(canonical);
    this.container.append(table);
    this.container.append(credits);
};

Details.prototype.render = function(node) {
    var _this = this;

    this.container.children('.canonical').text(node.getCanonicalName());

    var up = this.container.find('.up');
    up.off();
    if (node.parent) {
        up.prop('dispabled', true);
        up.click(function () {
            node.parent.select();
            if (node == _this.zoom.getZoom()) {
                _this.zoom.setZoom(node.parent);
            }
        });
    } else {
        up.prop('dispabled', false);
    }

    var down = this.container.find('.down');
    down.off();
    down.click(function () {
        _this.zoom.setZoom(node);
    });

    var mainTime  = node.getTime();
    var mainAlloc = node.getAlloc();
    var time      = mainTime;
    var alloc     = mainAlloc;

    var zoom = _this.zoom.getZoom();
    if (zoom.parent && zoom.getTime() > 0) {
        time = time * 100 / zoom.getTime();
    }
    if (zoom.parent && zoom.getAlloc() > 0) {
        alloc = alloc * 100 / zoom.getAlloc();
    }

    /* The default Number.prototype.toFixed adds 0s and we don't want that. */
    var precision = 3;
    function formatNum(value) {
        var power = Math.pow(10, precision || 0);
        return String(Math.round(value * power) / power);
    }

    this.container.find('.module').text(node.getModuleName());
    this.container.find('.entries').text(node.getEntries());
    this.container.find('.time').text(formatNum(time));
    this.container.find('.alloc').text(formatNum(alloc));
    this.container.find('.src').text(node.getSourceLoc().replace(/(^<|>$)/g, ""));
    this.container.find('.mainTime').text(formatNum(mainTime));
    this.container.find('.mainAlloc').text(formatNum(mainAlloc));

    if (zoom.parent) {
        this.container.find('.mainTimeRow').show();
        this.container.find('.mainAllocRow').show();
    } else {
        this.container.find('.mainTimeRow').hide();
        this.container.find('.mainAllocRow').hide();
    }
};

Details.prototype.onChange = function() {
    var node = this.selection.getSelectedNode();
    if (node) this.render(node);
};
